home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks ’87 / Source ƒ.sit / Source ƒ / C ƒ / CITADEL BBS 'C' SRC / ROOMA.C < prev    next >
C/C++ Source or Header  |  1987-01-14  |  25KB  |  799 lines

  1. /************************************************************************/
  2. /*                rooma.c                 */
  3. /*        room code for Citadel bulletin board system        */
  4. /************************************************************************/
  5.  
  6. /************************************************************************/
  7. /*                history                 */
  8. /*                                    */
  9. /*    SEE THE INCREM.* FILES FOR FURTHER HISTORICAL NOTES        */
  10. /* 84Jul12 JLS & HAW  gotoRoom() and dumpRoom() modified for <S>kip.    */
  11. /* 84Apr04 HAW    Start 1.50a update                    */
  12. /* 83Feb24    Insert check for insufficient RAM, externs too low.    */
  13. /* 82Dec06 CrT    2.00 release.                        */
  14. /* 82Nov05 CrT    main() splits off to become citadel.c            */
  15. /************************************************************************/
  16.  
  17. #include "ctdl.h"
  18.  
  19. /************************************************************************/
  20. /*                Contents                */
  21. /*                                    */
  22. /*    dumpRoom()        tells us # new messages etc        */
  23. /*    fDir()            prints out a filename for a dir listing */
  24. /*    fillMailRoom()        set up Mail> from log record        */
  25. /*    gotoRoom()        handles "g(oto)" command for menu    */
  26. /*    initCitadel()        system startup initialization        */
  27. /*    listRooms()        lists known rooms            */
  28. /*    openFile()        opens a .sys file            */
  29. /*    retRoom()        handle Ungoto command            */
  30. /*    roomExists()        returns slot# of named room else ERROR    */
  31. /*    searchRooms()        searches room list for matching string    */
  32. /*    setSpace()        set default disk and user#        */
  33. /*    setUp()                             */
  34. /*    systat()        shows current system status        */
  35. /*    wildCard()        expands ambiguous filenames        */
  36. /*                                    */
  37. /************************************************************************/
  38.  
  39. /************************************************************************/
  40. /*           external variable declarations in ROOMA.C        */
  41. /************************************************************************/
  42. FILE          *bannerFile;
  43. long          FDSectCount;        /* For accumulating dir. size    */
  44. char          debug;            /* debug flag            */
  45. char          *baseRoom;
  46. int          lastRoom;         /* last room visited        */
  47. char          remoteSysop = FALSE;    /* Is current user a sysop    */
  48. char          noBanner;
  49. int          lastPtr;
  50.  
  51. char    *bracket = "]";
  52. char    *arrow     = ">";
  53. char    *star     = "*";
  54. char    *dotdot  = "..";
  55.  
  56. static int    lPtrTab[MAXROOMS];    /* For .Ungoto            */
  57.  
  58. /************************************************************************/
  59. /*           external variable definitions for ROOMA.C        */
  60. /************************************************************************/
  61. extern struct config    cfg;        /* A buncha variables        */
  62. extern struct lTable    *logTab;    /* RAM index of pippuls     */
  63. extern struct logBuffer logBuf;     /* Pippul buffer        */
  64. extern FILE        *logfl;     /* log file descriptor        */
  65. extern FILE        *msgfl;     /* Message file descriptor    */
  66. extern FILE        *msgfl2;    /* Another for auto backup    */
  67. extern FILE        *netfl;     /* Net file            */
  68. extern struct rTable    roomTab[MAXROOMS]; /* RAM index of rooms    */
  69. extern struct aRoom    roomBuf;    /* room buffer            */
  70. extern FILE        *roomfl;    /* file descriptor for rooms    */
  71. extern int        thisRoom;    /* room currently in roomBuf    */
  72. extern char        loggedIn;    /* Are we logged in?        */
  73. extern char        expert;     /* Are we experienced??     */
  74. extern char        echo;        /* output flag            */
  75. extern char        prevChar;    /* Last char out        */
  76. extern char        termLF;     /* Need LF's?            */
  77. extern char        termUpper;    /* Only uppercase? Aw, foo    */
  78. extern char        aide;        /* aide?            */
  79. extern char        sendTime;    /* Send time message made?    */
  80. extern char        onConsole;    /* on console?            */
  81. extern char        whichIO;    /* where is the I/O?        */
  82. extern unsigned char    termNulls;    /* How many nulls?        */
  83. extern unsigned char    termWidth;    /* What's da termwidth?     */
  84. extern int        thisSlot;    /* Current log slot        */
  85. extern char        outFlag;
  86. extern char        nextDay;    /* System up before bailout?    */
  87. extern int        upDay;
  88. extern int        timeCrash;
  89. extern char        heldMess;
  90. extern char        oldToo;
  91. extern label        oldTarget;    /* Room to move messages to    */
  92.  
  93. /************************************************************************/
  94. /*           external function definitions for ROOMA.C        */
  95. /************************************************************************/
  96. char toUpper();
  97. FILE *safeopen();
  98. char *malloc();
  99. char *formRoom();
  100.  
  101. /************************************************************************/
  102. /*    dumpRoom() tells us # new messages etc                */
  103. /************************************************************************/
  104. dumpRoom()
  105. {
  106.     char  hasSkipped;
  107.     label str;
  108.     int   fDir();
  109.     int   i, count, newCount;
  110.  
  111.     for (newCount = count = i = 0;   i < MSGSPERRM;   i++) {
  112.                 /* Msg is still in system?  Count it.    */
  113.     if (roomBuf.msg[i].rbmsgNo >= cfg.oldest) {
  114.         count++;
  115.  
  116.         /* don't boggle -- just checking against newest as of */
  117.         /* the last time we were  in this room:          */
  118.         if (roomBuf.msg[i].rbmsgNo >
  119.               logBuf.lbvisit[ logBuf.lbgen[thisRoom] & CALLMASK ]) {
  120.         newCount++;
  121.         }
  122.     }
  123.     }
  124.     if (!loggedIn && thisRoom == MAILROOM)    /* Kludge for new users */
  125.     newCount = count = 1;            /* So they see intro.    */
  126.  
  127.     mPrintf(" %d messages\n ", count);
  128.     if ((thisRoom == MAILROOM || loggedIn) && newCount > 0)
  129.     mPrintf(" %d new\n", newCount);
  130.  
  131.     if (thisRoom == LOBBY) {
  132.     for (i = LOBBY, hasSkipped = FALSE; i < MAXROOMS; i++)
  133.         if (roomTab[i].rtflags.INUSE == 1 &&
  134.                roomTab[i].rtgen == (logBuf.lbgen[i] >> GENSHIFT)) {
  135.         if (roomTab[i].rtflags.SKIP == 1)
  136.             hasSkipped = TRUE;
  137.         else
  138.             if (roomTab[i].rtlastMessage > (
  139.                 logBuf.lbvisit[logBuf.lbgen[i] & CALLMASK] + 1))
  140.             break;
  141.         }
  142.  
  143.     if (i == MAXROOMS && hasSkipped) {
  144.         mPrintf("\n Skipped rooms: \n ");
  145.       for (i = LOBBY; i < MAXROOMS; i++)      /* No need to match gen #s. */
  146.         if (roomTab[i].rtflags.SKIP == 1 &&
  147.                roomTab[i].rtflags.INUSE == 1) {
  148.             roomTab[i].rtflags.SKIP = 0;           /* Clear. */
  149.             mPrintf(" %s ", formRoom(i, TRUE));
  150.         }
  151.     }
  152.     }
  153. }
  154.  
  155. /************************************************************************/
  156. /*    fDir() prints out one filename and size, for a dir listing   */
  157. /************************************************************************/
  158. fDir(fileName)
  159. char *fileName;
  160. {
  161.     FILE *temp;
  162.     long fseek(), size, Sectors;
  163.  
  164.     outFlag = OUTOK;
  165.     if ((temp = safeopen(fileName, "rb")) == NULL)
  166.     return mPrintf("\n ?Can't find file size for %s!", fileName);
  167.  
  168.     size    = (fseek(temp, -1l, 2)+1);
  169.     Sectors    = ((size + 127) / SECTSIZE);
  170.     FDSectCount += Sectors;
  171.  
  172.     mPrintf("%-15s%5ld%2c", fileName, Sectors, ' ');
  173.     mAbort();        /* chance to next(!)/pause/skip */
  174.     fclose(temp);
  175. }
  176.  
  177. /************************************************************************/
  178. /*    fillMailRoom()                            */
  179. /************************************************************************/
  180. fillMailRoom()
  181. {
  182.     int i;
  183.  
  184.     /* mail room -- copy messages in logBuf to room: */
  185.     for (i = 0;  i < MSGSPERRM;  i++) {
  186.     roomBuf.msg[i].rbmsgNo     = 0l;    /* Marks "no" msg */
  187.     roomBuf.msg[i].rbmsgLoc  = 0 ;    /* Jest fer fun   */
  188.     }
  189.     for (i = 0;  i < MAILSLOTS;  i++) {
  190.     if (i == MSGSPERRM)   break;  /* for MSGSPRRM < MAILSLOTS */
  191.     roomBuf.msg[i].rbmsgLoc  = logBuf.lbslot[i];
  192.     roomBuf.msg[i].rbmsgNo     = logBuf.lbId[i]  ;
  193.     }
  194.     noteRoom();
  195. }
  196.  
  197. /************************************************************************/
  198. /*    gotoRoom() is the menu fn to travel to a new room        */
  199. /*    returns TRUE if room is Lobby>, else FALSE            */
  200. /************************************************************************/
  201. gotoRoom(nam, mode)
  202. char *nam, mode;
  203. {
  204.     int  i, foundit, roomNo;
  205.     int  lPtr, lRoom;
  206.     int  roomExists(), partialExist();
  207.  
  208.     lRoom = thisRoom;
  209.     lPtr  = (logBuf.lbgen[thisRoom] & CALLMASK);
  210.  
  211.     if (strLen(nam) == 0) {
  212.  
  213.     foundit = FALSE;    /* leaves us in Lobby> if nothing found */
  214.     if (mode != 'S') {
  215.         if (loggedIn)
  216.         logBuf.lbgen[thisRoom] = roomBuf.rbgen << GENSHIFT;
  217.         roomTab[thisRoom].rtflags.SKIP = 0;
  218.     }
  219.  
  220.     for (i = 0; i<MAXROOMS    &&  !foundit; i++) {
  221.         if (
  222.         roomTab[i].rtflags.INUSE == 1
  223.         &&
  224.         (roomTab[i].rtgen == (logBuf.lbgen[i] >> GENSHIFT) || aide)
  225.         &&
  226.         roomTab[i].rtflags.SKIP == 0
  227.         ) {
  228.         if (roomTab[i].rtlastMessage >
  229.             logBuf.lbvisit[logBuf.lbgen[i] & CALLMASK] &&
  230.             roomTab[i].rtlastMessage >= cfg.oldest) {
  231.  
  232.             if (i != thisRoom && (i != AIDEROOM || aide)) {
  233.             foundit  = i;
  234.             }
  235.         }
  236.         }
  237.     }
  238.  
  239.     lastRoom = lRoom;
  240.     lastPtr  = lPtr;
  241.     getRoom(foundit);
  242.     mPrintf("%s\n ", roomBuf.rbname);
  243.     } else {
  244.     foundit = 0;
  245.     /* non-empty room name, so now we look for it: */
  246.     if (
  247.         (roomNo = roomCheck(roomExists, nam)) == ERROR &&
  248.         (roomNo = roomCheck(partialExist, nam)) == ERROR
  249.     ) {
  250.         mPrintf(" ?no %s room\n", nam);
  251.     } else {
  252.         foundit = roomNo;
  253.         if (mode != 'S') {
  254.         if (loggedIn)
  255.             logBuf.lbgen[thisRoom] = roomBuf.rbgen << GENSHIFT;
  256.         roomTab[thisRoom].rtflags.SKIP = 0;
  257.         }
  258.         lastRoom = lRoom;        /* For Ungoto            */
  259.         lastPtr  = lPtr;
  260.         getRoom(roomNo);
  261.  
  262.         /* if may have been unknown... if so, note it:    */
  263.         if ((logBuf.lbgen[thisRoom] >> GENSHIFT) != roomBuf.rbgen) {
  264.         logBuf.lbgen[thisRoom] = (
  265.             (roomBuf.rbgen << GENSHIFT) +
  266.             (MAXVISIT -1)
  267.         );
  268.         }
  269.     }
  270.     }
  271.  
  272.     setUp(FALSE);
  273.     dumpRoom();
  274.     return foundit;
  275. }
  276.  
  277. /************************************************************************/
  278. /*    initCitadel() does not reformat data files            */
  279. /************************************************************************/
  280. initCitadel()
  281. {
  282.     char *msgFile;
  283.     char *msg2File;
  284.     char *roomFile;
  285.     char *logFile;
  286.     char *netFile;
  287.     char *mon;
  288.     int  yr, hr, mn;
  289.  
  290.     if (!readSysTab(TRUE))
  291.     exit(CRASH_EXIT);/* No system table? Tacky, tacky*/
  292.     cfg.weAre = CITADEL;
  293.     setSpace(cfg.homeDisk, "");
  294.  
  295.     strCpy(oldTarget, "Aide");
  296.  
  297.     baseRoom = &cfg.codeBuf[cfg.bRoom];
  298.  
  299.     setUp(TRUE);
  300.  
  301.     /* we initmodem at beginning & end both...*/
  302.     modemInit();
  303.     getDate(&yr, &mon, &upDay, &hr, &mn);
  304.     timeCrash = hr + cfg.hourOut;
  305.     if ((nextDay = (timeCrash > 23))) timeCrash %= 24;
  306.  
  307. #ifndef MSDOS
  308.     if (!cfg.clock)   interpret(cfg.pInitDate);
  309. #endif
  310.  
  311.     /* open message files: */
  312.     msgFile    = "a:ctdlmsg.sys";
  313.     msg2File    = "a:ctdlmsg.sys";
  314.     logFile    = "a:ctdllog.sys";
  315.     roomFile    = "a:ctdlroom.sys";
  316.     netFile    = "a:ctdlnet.sys";
  317.     *msgFile   += cfg.msgDisk;
  318.     *roomFile  += cfg.sysDisk;
  319.     *logFile   += cfg.sysDisk;
  320.     *netFile   += cfg.netDisk;
  321.     if (cfg.mirror) {
  322.     *msg2File += cfg.mbkpDisk;
  323.     openFile(msg2File,  &msgfl2);
  324.     }
  325.     openFile(msgFile,  &msgfl );
  326.     openFile(roomFile, &roomfl);
  327.     openFile(logFile,  &logfl );
  328.     openFile(netFile,  &netfl );
  329.  
  330.     noBanner = ((bannerFile = safeopen("banner.blb", "r")) == NULL);
  331.  
  332.     initArchiveList();
  333. #ifdef MSDOS
  334.     initBadList();        /* MS-DOS only */
  335. #endif
  336.  
  337.     getRoom(LOBBY);    /* load Lobby>    */
  338.     setSharedRooms();
  339.     modemInit();
  340.     whichIO = MODEM;
  341.     setUp(FALSE);
  342. }
  343.  
  344. /************************************************************************/
  345. /*    legalMatch() Looks for partial matches, checks legalities    */
  346. /************************************************************************/
  347. legalMatch(i, target)
  348. label target;
  349. int i;
  350. {
  351.     char  Equal, *endbuf, *matchString();
  352.  
  353.     Equal = (roomTab[i].rtgen == (logBuf.lbgen[i] >> GENSHIFT));
  354.     if ((roomTab[i].rtflags.INUSE == 1) && (debug || aide || Equal)) {
  355.     for (endbuf = roomTab[i].rtname; *endbuf; endbuf++);
  356.     return (matchString(roomTab[i].rtname, target, endbuf) != NULL);
  357.     }
  358.     return FALSE;
  359. }
  360.  
  361. /************************************************************************/
  362. /*    listRooms() lists known rooms                    */
  363. /************************************************************************/
  364. listRooms(what)
  365. unsigned int what;
  366. {
  367.     int     difference, diff, i, j;
  368.     char    str[NAMESIZE+3];
  369.     char    shownHidden, isPublic, showPrivate, msgF, hasUnseenStuff;
  370.     static char *legends[] =
  371.         { "Forgotten public rooms",
  372.           "Rooms with unread messages",
  373.           "No unseen msgs in"         } ;
  374.  
  375.     mPrintf("\n %s:\n ", legends[(what & 0x000f)]);
  376.     showPrivate = ((what & 0x00C0) > 4);
  377.     msgF    = ((what & 0x0030) > 4);
  378.     diff = (what == FGTRMS) ? FORGET_OFFSET : 0;
  379.  
  380.     shownHidden = FALSE;
  381.     for (i = 0; i < MAXROOMS;  i++) {
  382.     if (roomTab[i].rtflags.INUSE) {
  383.         j = roomTab[i].rtgen - (logBuf.lbgen[i] >> GENSHIFT);
  384.         difference = abs(j);
  385.         isPublic   = roomTab[i].rtflags.PUBLIC;
  386.         if (difference == diff && (showPrivate || isPublic)) {
  387.         hasUnseenStuff    =  (roomTab[i].rtlastMessage > cfg.oldest &&
  388.             roomTab[i].rtlastMessage >= (
  389.             logBuf.lbvisit[ logBuf.lbgen[i] & CALLMASK ]+1));
  390.         if (what == FGTRMS ||
  391.             (what == NOROLD && !hasUnseenStuff) ||
  392.            ((what == NORNEW || what == LINNEW) && hasUnseenStuff)) {
  393.             mPrintf(" %s ", formRoom(i, TRUE));
  394.         }
  395.         }
  396.     }
  397.     }
  398.     if (!expert && shownHidden && msgF) mPrintf("\n \n * => hidden room\n ");
  399. }
  400.  
  401. /************************************************************************/
  402. /*    knowRoom() check to see if current person knows given room    */
  403. /*    Return 0 if not know room, 2 if forgot room, 1 otherwise    */
  404. /************************************************************************/
  405. knowRoom(i)
  406. int i;
  407. {
  408.     int difference;
  409.  
  410.     difference = abs(roomTab[i].rtgen - (logBuf.lbgen[i] >> GENSHIFT));
  411.     return ((difference == 0) ? 1 : ((difference == FORGET_OFFSET) ? 2 : 0));
  412. }
  413.  
  414. /************************************************************************/
  415. /*    openFile() opens one of the .sys files.             */
  416. /************************************************************************/
  417. openFile(filename, fd)
  418. char *filename;
  419. FILE **fd;
  420. {
  421.     /* open message file */
  422.     if ((*fd = safeopen(filename, "rwb")) == NULL) {
  423.     printf("?no %s", filename);
  424.     exit(SYSOP_EXIT);
  425.     }
  426. }
  427.  
  428. /************************************************************************/
  429. /*    partialExist() roams the list looking for a partial match    */
  430. /************************************************************************/
  431. partialExist(target)
  432. label target;
  433. {
  434.     int rover;
  435.  
  436.     for (rover = (thisRoom + 1) % MAXROOMS; rover != thisRoom;
  437.                         rover = (rover + 1) % MAXROOMS)
  438.     if (legalMatch(rover, target)) return rover;
  439.     return ERROR;
  440. }
  441.  
  442. /************************************************************************/
  443. /*    retRoom() Ungoto command                    */
  444. /************************************************************************/
  445. retRoom(roomName)
  446. char *roomName;
  447. {
  448.     int slot;
  449.     int roomExists(), partialExist();
  450.  
  451.     if (strLen(roomName) == 0) {
  452.     if (lastRoom == -1) {
  453.         mPrintf("No room to Ungoto to!\n ");
  454.         return;
  455.     }
  456.     getRoom(lastRoom);
  457.       logBuf.lbgen[thisRoom] = (logBuf.lbgen[thisRoom] & (~CALLMASK)) + lastPtr;
  458.     lastRoom = -1;
  459.     }
  460.     else {
  461.     if (
  462.         (slot = roomCheck(roomExists, roomName)) == ERROR &&
  463.         (slot = roomCheck(partialExist, roomName)) == ERROR
  464.     ) {
  465.         mPrintf(" ?no %s room\n", roomName);
  466.         return;
  467.     }
  468.     lastRoom = thisRoom;
  469.     lastPtr  = (logBuf.lbgen[thisRoom] & CALLMASK);
  470.     getRoom(slot);
  471.     logBuf.lbgen[thisRoom] = lPtrTab[thisRoom];
  472.     }
  473.     setUp(FALSE);
  474.     dumpRoom();
  475. }
  476.  
  477. /************************************************************************/
  478. /*    roomCheck() returns slot# of named room else ERROR        */
  479. /************************************************************************/
  480. roomCheck(checker, nam)
  481. int (*checker)();
  482. char *nam;
  483. {
  484.     int roomNo;
  485.  
  486.     if (
  487.     (roomNo = (*checker)(nam)) == ERROR
  488.     ||
  489.     (roomNo==AIDEROOM  &&  !aide)
  490.     ||
  491.     (roomTab[roomNo].rtflags.PUBLIC == 0 && !loggedIn)
  492.     )
  493.     return ERROR;
  494.     return roomNo;
  495. }
  496.  
  497. /************************************************************************/
  498. /*    roomExists() returns slot# of named room else ERROR        */
  499. /************************************************************************/
  500. int roomExists(room)
  501. char *room;
  502. {
  503.     int i;
  504.  
  505.     for (i = 0;  i < MAXROOMS;    i++) {
  506.     if (
  507.         roomTab[i].rtflags.INUSE == 1   &&
  508.         strCmpU(room, roomTab[i].rtname) == SAMESTRING
  509.     ) {
  510.         return(i);
  511.     }
  512.     }
  513.     return(ERROR);
  514. }
  515.  
  516. /************************************************************************/
  517. /*    searchRooms() searches for user string in list of rooms     */
  518. /************************************************************************/
  519. searchRooms()
  520. {
  521.     label target;
  522.     char  str[NAMESIZE+5];
  523.     int   i;
  524.  
  525.     getNormStr("", target, NAMESIZE, ECHO);
  526.  
  527.     mPrintf("Matching rooms:\n ");
  528.     outFlag = OUTOK;
  529.  
  530.     for (i = 0; i < MAXROOMS;  i++) {
  531.     if (legalMatch(i, target)) {
  532.         mPrintf(" %s ", formRoom(i, TRUE));
  533.     }
  534.     }
  535. }
  536.  
  537. /************************************************************************/
  538. /*    setSpace() moves us to a disk and directory            */
  539. /************************************************************************/
  540. #define SETDISK     14
  541. setSpace(disk, dir)
  542. char disk;
  543. char *dir;
  544. {
  545.     bdos(SETDISK, disk);
  546.     cfg.ourDisk     = disk;
  547.  
  548.     if (strCmp(dir, "") == SAMESTRING) {
  549.     strCpy(cfg.ourUser, dotdot);
  550.     }
  551.     else {
  552.     strCpy(cfg.ourUser, dir);
  553.     if (chdir(dir) == EOF) {
  554.         mPrintf("?Directory not present!\n ");
  555.         setSpace(cfg.homeDisk, "");
  556.         return FALSE;
  557.     }
  558.     }
  559.     return TRUE;
  560. }
  561.  
  562. /************************************************************************/
  563. /*    setUp()                             */
  564. /************************************************************************/
  565. setUp(justIn)
  566. char justIn;
  567. {
  568.     int g, i, j, ourSlot;
  569.  
  570.     echo        = BOTH;     /* just in case         */
  571.  
  572.     if (!loggedIn)   {
  573.     remoteSysop = FALSE;
  574.     prevChar    = ' ';
  575.     termWidth   = 32;
  576.     termLF        = TRUE;
  577.     termUpper   = FALSE;
  578.     termNulls   = 5;
  579.     expert        = FALSE;
  580.     aide        = FALSE;
  581.     sendTime    = TRUE;
  582.     oldToo        = FALSE;
  583.  
  584.     if (justIn)   {
  585.         /* set up logBuf so everything is new...        */
  586.         lastRoom = -1;
  587.             heldMess = FALSE;
  588.         for (i = 0; i < MAXVISIT;  i++)  logBuf.lbvisit[i] = cfg.oldest;
  589.  
  590.         /* no mail for anonymous folks: */
  591.         roomTab[MAILROOM].rtlastMessage = cfg.newest;
  592.         for (i = 0; i < MAILSLOTS;    i++)   logBuf.lbId[i]  = 0l;
  593.  
  594.         logBuf.lbname[0] = 0;
  595.  
  596.         for (i = 0; i < MAXROOMS;  i++) {
  597.         if (roomTab[i].rbflags.PUBLIC == 1) {
  598.             /* make public rooms known: */
  599.             g            = roomTab[i].rtgen;
  600.             logBuf.lbgen[i] = (g << GENSHIFT) + (MAXVISIT-1);
  601.         } else {
  602.             /* make private rooms unknown: */
  603.             g            = (roomTab[i].rtgen + (MAXGEN-1)) % MAXGEN;
  604.             logBuf.lbgen[i] = (g << GENSHIFT) + (MAXVISIT-1);
  605.         }
  606.         lPtrTab[i]  = logBuf.lbgen[i];
  607.         }
  608.     }
  609.     } else {
  610.     /* loggedIn: */
  611.     termWidth   = logBuf.lbwidth;
  612.     termNulls   = logBuf.lbnulls;
  613.     termLF        = (logBuf.lbflags.LFMASK == 1) ? TRUE : FALSE ;
  614.     termUpper   = (logBuf.lbflags.UCMASK == 1) ? TRUE : FALSE ;
  615.     expert        = (logBuf.lbflags.EXPERT == 1) ? TRUE : FALSE ;
  616.     aide        = (logBuf.lbflags.AIDE   == 1) ? TRUE : FALSE ;
  617.     sendTime    = (logBuf.lbflags.TIME   == 1) ? TRUE : FALSE ;
  618.     oldToo        = (logBuf.lbflags.OLDTOO == 1) ? TRUE : FALSE ;
  619.  
  620.     if (justIn)   {
  621.         remoteSysop = FALSE;
  622.         lastRoom = -1;
  623.         heldMess = FALSE;
  624.         /* set gen on all unknown rooms  --  INUSE or no: */
  625.         for (i = 0;  i < MAXROOMS;    i++) {
  626.         if (roomTab[i].rtflags.PUBLIC == 0) {
  627.             /* it is private -- is it unknown? */
  628.             if (((logBuf.lbgen[i] >> GENSHIFT) != roomTab[i].rtgen) ||
  629.              (!aide && i == AIDEROOM)
  630.                ) {
  631.             /* yes -- set    gen = (realgen-1) % MAXGEN */
  632.             j = (roomTab[i].rtgen + (MAXGEN-1)) % MAXGEN;
  633.             logBuf.lbgen[ i ] =  (j << GENSHIFT) + (MAXVISIT-1);
  634.             }
  635.         }
  636.         else if ((logBuf.lbgen[i] >> GENSHIFT) != roomTab[i].rtgen)  {
  637.             /* newly created public room -- remember to visit it; */
  638.             j = roomTab[i].rtgen - (logBuf.lbgen[i] >> GENSHIFT);
  639.             if (j < 0)
  640.             g = -j;
  641.             else
  642.             g = j;
  643.             if (g != FORGET_OFFSET) {
  644.             logBuf.lbgen[i] = (roomTab[i].rtgen << GENSHIFT) +1;
  645.             }
  646.         }
  647.         }
  648.         /* special kludge for Mail> room, to signal new mail:   */
  649.         roomTab[MAILROOM].rtlastMessage = logBuf.lbId[MAILSLOTS-1];
  650.  
  651.         /* slide lbvisit array down and change lbgen entries to match: */
  652.         for (i = (MAXVISIT - 2);  i;  i--) {
  653.         logBuf.lbvisit[i] = logBuf.lbvisit[i-1];
  654.         }
  655.         logBuf.lbvisit[(MAXVISIT - 1)]    = cfg.oldest;
  656.         for (i = 0;  i < MAXROOMS;    i++) {
  657.         if ((logBuf.lbgen[i] & CALLMASK)  <  (MAXVISIT-2)) {
  658.             logBuf.lbgen[i]++;
  659.         }
  660.         lPtrTab[i]  = logBuf.lbgen[i];
  661.         }
  662.  
  663.         /* Slide entry to top of log table: */
  664.         ourSlot = logTab[thisSlot].ltlogSlot;
  665.         slideltab(0, thisSlot);
  666.  
  667.         logTab[0].ltpwhash        = hash(logBuf.lbpw);
  668.         logTab[0].ltnmhash        = hash(logBuf.lbname);
  669.         logTab[0].ltlogSlot     = ourSlot;
  670.         logTab[0].ltnewest        = cfg.newest;
  671.     }
  672.     }
  673.     logBuf.lbvisit[0]    = cfg.newest;
  674.  
  675.     onConsole    = (whichIO == CONSOLE);
  676.     if (thisRoom == MAILROOM)    fillMailRoom();
  677. }
  678.  
  679. /************************************************************************/
  680. /*    systat() prints out current system status            */
  681. /************************************************************************/
  682. systat()
  683. {
  684.     extern char *VERSION;
  685.     int   i, year, day, hours, minutes;
  686.     char  *month, *m;
  687.     ulong average, work;
  688.     int   roomCount;
  689.     unsigned exportSector();
  690.  
  691.     for (roomCount = i = 0; i < MAXROOMS; i++)
  692.     if (roomTab[i].rtflags.INUSE) roomCount++;
  693.  
  694.     getdate(&year, &month, &day, &hours, &minutes);
  695.     if (hours >= 12)
  696.     m = "pm";
  697.     else
  698.     m = "am";
  699.     if (hours >= 13)
  700.     hours -= 12;
  701.     if (hours == 0)
  702.     hours = 12;
  703.  
  704.     mPrintf("This is %s\n ", &cfg.codeBuf[cfg.nodeTitle]);
  705.     mPrintf("%d%s%02d %d:%02d %s (V%s)\n",
  706.              year, month, day, hours, minutes, m, VERSION);
  707.  
  708.     if (loggedIn) {
  709.     mPrintf(" Logged in as %s\n", logBuf.lbname);
  710.     if (logBuf.lbflags.NET_PRIVS)
  711.         mPrintf(" You have net privileges, %d LD credits\n",
  712.             logBuf.credit);
  713.     }
  714.     mPrintf(" %ld messages,",           cfg.newest-cfg.oldest +1);
  715.     mPrintf(" last is %lu,\n",           cfg.newest           );
  716.     mPrintf(" %dK message space,\n",       cfg.maxMSector >> 3       );
  717.     mPrintf(" %d-entry log\n",           cfg.MAXLOGTAB       );
  718.     mPrintf(" %d room slots, %d in use\n", MAXROOMS, roomCount);
  719.     if (cfg.oldest > 1)
  720.     work = cfg.maxMSector;
  721.     else
  722.     work = cfg.catSector;
  723.     work *= 128;
  724.     if (cfg.oldest > 1)
  725.     average = (work) / (cfg.newest - cfg.oldest + 1);
  726.     else
  727.     average = (work) / (cfg.newest);
  728.     mPrintf(" Average message length: %ld\n",  average);
  729.     if (cfg.debug) printf("Sector to write to: %u\n", exportSector());
  730. }
  731.  
  732. struct dirList {
  733.    char *unambig;
  734. } ;
  735.  
  736. /************************************************************************/
  737. /*    wildCard() Do something with the directory            */
  738. /************************************************************************/
  739. #define UFNsIZE     13    /* size of "filename.ext" plus a null.    */
  740. #define DIR_SIZE    600
  741.  
  742. wildCard(fn, filename)
  743. int (*fn)();
  744. char *filename;     /* may be ambiguous.  No drive or user numbers. */
  745. {
  746.     int  i, s, sortDir(), fileCount;
  747.     struct dirList *fp, list[DIR_SIZE];
  748.     char *FileList, *ls, *filedir();
  749.  
  750.     if (!setSpace(roomBuf.rbdisk, roomBuf.rbdirname)) return;
  751.  
  752.          /* This is where file names should be made usable */
  753.     if (filename[1] != ':')
  754.     ls = FileList = filedir(filename, 0);
  755.  
  756.     if (filename[1] == ':' || !(*FileList)) {
  757.     /* no such file */
  758.     mPrintf("no %s\n ", filename);
  759.     if (strLen(roomBuf.rbdirname) != 0)
  760.         setSpace(roomBuf.rbdisk, dotdot);
  761.     setSpace(cfg.homeDisk, "");
  762.     if (filename[1] != ':')
  763.         free(ls);
  764.     return;
  765.     }
  766.  
  767.     fp          = list;
  768.     fileCount = 0;
  769.  
  770.     while (*FileList) {
  771.     if (fileCount >= DIR_SIZE) {
  772.         mPrintf("too many files!!\n ");
  773.         setSpace(roomBuf.rbdisk, dotdot);
  774.         setSpace(cfg.homeDisk, "");
  775.         return;
  776.     }
  777.     fp->unambig = FileList;
  778.     while (*FileList) FileList++;
  779.     FileList++;
  780.     fp++;
  781.     fileCount++;
  782.     }
  783.  
  784.     qSort(list, fileCount, sizeof list[0], sortDir);
  785.     outFlag    = OUTOK;
  786.     for (fp = list;  fileCount-- && outFlag != OUTSKIP;  fp++)
  787.     (*fn)(fp->unambig);
  788.     if (strLen(roomBuf.rbdirname) != 0)
  789.     setSpace(roomBuf.rbdisk, dotdot);
  790.     setSpace(cfg.homeDisk, "");
  791.     free(ls);
  792. }
  793.  
  794. sortDir(s1, s2)
  795. struct dirList *s1, *s2;
  796. {
  797.     return strCmp(s1->unambig, s2->unambig);
  798. }
  799.